package com.douqu.game.main.server;

import com.alibaba.fastjson.JSONObject;
import com.bean.core.util.HttpJsonUtils;
import com.bean.core.util.Utils;
import com.douqu.game.core.config.*;
import com.douqu.game.core.config.activity.SevenActivitiesConfig;
import com.douqu.game.core.config.activity.SevenTabConfig;
import com.douqu.game.core.config.challenge.WorldBossConfig;
import com.douqu.game.core.config.common.CommonData;
import com.douqu.game.core.config.common.GoodsData;
import com.douqu.game.core.config.hegemony.HegemonyRankRewardConfig;
import com.douqu.game.core.config.hegemony.HegemonyRankRewardGroupConfig;
import com.douqu.game.core.config.map.*;
import com.douqu.game.core.container.PlayerContainer;
import com.douqu.game.core.controller.PlayerController;
import com.douqu.game.core.database.model.DiamondsChangeModel;
import com.douqu.game.core.database.model.GMModel;
import com.douqu.game.core.database.model.PlayerModel;
import com.douqu.game.core.database.model.ServerModel;
import com.douqu.game.core.e.*;
import com.douqu.game.core.entity.Player;
import com.douqu.game.core.entity.activity.RankPlayer;
import com.douqu.game.core.entity.battle.BattleInitParamWorldMap;
import com.douqu.game.core.entity.battle.BattleTemp;
import com.douqu.game.core.entity.common.TwoTuple;
import com.douqu.game.core.entity.db.MailDB;
import com.douqu.game.core.entity.ext.*;
import com.douqu.game.core.entity.ext.data.boon.AuctionRewardPlayer;
import com.douqu.game.core.entity.ext.data.challenge.HegemonyScoreChangeBean;
import com.douqu.game.core.entity.ext.data.challenge.WorldMapKillBean;
import com.douqu.game.core.entity.ext.data.challenge.WorldMapTaskData;
import com.douqu.game.core.entity.world.*;
import com.douqu.game.core.entity.world.map.*;
import com.douqu.game.core.factory.*;
import com.douqu.game.core.netty.NettyConnection;
import com.douqu.game.core.protobuf.SGCommonProto;
import com.douqu.game.core.util.CoreUtils;
import com.douqu.game.core.util.LogUtils;
import com.douqu.game.core.util.SendUtils;
import com.douqu.game.core.util.time.TimeData;
import com.douqu.game.core.util.time.TimeUtils;
import com.douqu.game.main.GameServer;
import com.douqu.game.main.database.mapper.read.ReadPlayerMapper;
import com.douqu.game.main.gui.MainFrame;
import com.douqu.game.main.msg.BoonMsgChannel;
import com.douqu.game.main.server.entity.*;
import com.douqu.game.main.server.netty.NettyTCPServerHandler;
import com.douqu.game.main.service.DiamondsChangeService;
import com.douqu.game.main.service.PlayerService;
import com.douqu.game.main.service.WorldService;
import com.douqu.game.main.util.MsgUtils;
import com.douqu.game.main.util.WorldMapUtils;
import com.douqu.game.core.util.StringUtils;
import io.netty.buffer.ByteBuf;
import org.springframework.beans.factory.annotation.Autowired;

import java.sql.Time;
import java.text.MessageFormat;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.concurrent.atomic.AtomicInteger;

/**
 * Created by bean on 2017/7/27.
 */
public class WorldManager extends PlayerContainer {

    @Autowired
    private PlayerService playerService;

    /**登录等待用户列表*/
    private List<WaitPlayer> waitPlayerList = new LinkedList<>();

    private Map<String, WaitPlayer> waitPlayerMap = new ConcurrentHashMap<>();

    /**
     * 所有连接(包含未登录的)
     */
    private List<NettyConnection> connections = new CopyOnWriteArrayList<>();
    /**
     * 所有在线的GM
     */
    private List<NettyConnection> gmList = new CopyOnWriteArrayList<>();

    private Map<String, PlayerController> playerIndexMap = new ConcurrentHashMap<>();

    /**
     * 排行榜的玩家详情(要显示在客户端的数据)
     */
    private Map<String, RankPlayerDetail> rankPlayerDetailMap = new ConcurrentHashMap<>();

    /**
     * 发送的公告列表
     */
    private List<NoticeInfo> gmNoticeList = new CopyOnWriteArrayList<>();

    /**
     * 发送的公告列表
     */
    private List<NoticeInfo> getNoticeList = new CopyOnWriteArrayList<>();
    /**
     * 为同步人数增加字段
     */
    private int currentPlayerCount;
    /**
     * 群发邮件列表
     */
    private List<MailGroup> mailGroupList = new CopyOnWriteArrayList<>();

    /**
     * 临时保存的战斗数据
     */
    private Map<Integer, Map<String, BattleTemp>> spriteBattleTempMap = new ConcurrentHashMap<>();

    /**
     * 战斗中的玩家,缓存一下，用来针对客户端的BUG做容错处理
     */
    private Map<String, BattleCachePlayer> battlePlayerCacheMap = new ConcurrentHashMap<>();

    private List<String> whiteList = new ArrayList<>();

    /**
     * 正在进行验证的订单
     */
    private List<String> verifyingTradeList = new CopyOnWriteArrayList<>();


    public WorldManager() {
    }

    /****************************************************************************************************************************/


    public void addCachePlayer(){
        currentPlayerCount ++;
    }
    public void reduceCachePlayer(){
        if(currentPlayerCount > 0){
            currentPlayerCount --;
        }
    }


    public void load(ServerModel... serverModels)
    {
        WorldInfoFactory worldInfo = WorldInfoFactory.getInstance();
        PlayerService playerService = SpringContext.getBean(PlayerService.class);
        worldInfo.collectRobotPlayerIndex = playerService.getRobotPlayerByMaxCount(100);

        WorldMapData worldMapData = worldInfo.getWorldMapData();
        int averageLv = playerService.getWorldPlayerAverageLevel(10, 0);
        worldMapData.setPlayerAverageLevel(averageLv);
        if(serverModels.length > 0)
        {
            worldInfo.load(serverModels[0]);
        }
        else
        {
            WorldService worldService = SpringContext.getBean(WorldService.class);

            ServerModel serverModel = worldService.find();

            worldInfo.load(serverModel);
        }

        Map<Integer, CityBean> cityMap = worldMapData.getCityMap();
        List<String> playerIndexList = new CopyOnWriteArrayList<>();
        for(CityBean cityBean : cityMap.values())
        {
            for(SpritePlayerBean spritePlayerBean : cityBean.getSpritePlayerList())
            {
                playerIndexList.add(spritePlayerBean.getObjectIndex());
            }
        }

        Map<String, WorldMapData> playerWorldMap = worldInfo.getPlayerWorldMapDataMap();

        playerIndexList.addAll(playerWorldMap.keySet());

        List<PlayerModel> playerModelList = new ArrayList<>();
        //设置大地图中玩家数据
        if(!playerIndexList.isEmpty())
        {
            playerModelList = playerService.getPlayerListByIndex(playerIndexList);
        }

        checkWorldMap(worldMapData, playerModelList);

        int index = -1;
        //单人战场
        PlayerModel playerModel = null;
        for(Map.Entry<String, WorldMapData> entry : playerWorldMap.entrySet())
        {
            index = playerModelList.indexOf(new PlayerModel(entry.getKey()));
            if(index >= 0)
            {
                playerModel = playerModelList.get(index);
                FunctionConfig functionConfig = DataFactory.getInstance().getGameObject(DataFactory.FUNCTION_KEY, FunctionFactory.INTO_WORLD_MAP);
                StableDataConfig stableDataConfig = DataFactory.getInstance().getGameObject(DataFactory.STABLE_DATA_KEY, E_StableDataType.WORLD_MAP.getCode());
                if(playerModel.getLevel() < functionConfig.lv || playerModel.getLevel() >= stableDataConfig.intValue)
                {
                    //之前因为异常生成了单人战场数据，现在删除
                    LogUtils.info("删除异常生成或者超过等级的的单人战场数据 -> " + playerModel.getName() + " Lv." + playerModel.getLevel());
                    WorldInfoFactory.getInstance().removePlayerWorldMap(entry.getKey());
                }
                else
                {
                    entry.getValue().setPlayerAverageLevel(playerModel.getLevel());

                    checkWorldMap(entry.getValue(), playerModelList);
                }
            }
        }

        Map<Integer, List<WorldRankBean>> rankMap = worldInfo.getWorldRankData().getRankMap();

        Map<String, Object> tempMap = new HashMap<>();
        List<String> ids = new ArrayList<>();
        for(List<WorldRankBean> list : rankMap.values())
        {
            for(WorldRankBean bean : list)
            {
                if(tempMap.get(bean.getObjectIndex()) == null)
                {
                    tempMap.put(bean.getObjectIndex(), bean);
                    ids.add(bean.getObjectIndex());
                }
            }
        }

        if(ids.size() > 0)
        {
            playerModelList = playerService.getPlayerListByIndex(ids);
            for(PlayerModel model : playerModelList)
            {
                updateRankPlayerDetail(model);
            }
        }
    }

    private void checkWorldMap(WorldMapData worldMapData, List<PlayerModel> playerModelList)
    {
        Map<Integer, CityBean> cityMap = worldMapData.getCityMap();

        PlayerModel playerModel = null;
        int index = -1;
        for(CityBean cityBean : cityMap.values())
        {
            for(SpritePlayerBean spritePlayerBean : cityBean.getSpritePlayerList())
            {
                spritePlayerBean.setCurCity(cityBean.id);

                index = playerModelList.indexOf(new PlayerModel(spritePlayerBean.getObjectIndex()));
                if(index >= 0)
                {
                    playerModel = playerModelList.get(index);
                    spritePlayerBean.setCamp(playerModel.getCamp());
                    spritePlayerBean.updatePlayer(new Player(playerModel));
                    spritePlayerBean.setTeam(worldMapData.isAlly(spritePlayerBean.getCamp(), cityBean.camp) ? SGCommonProto.E_ARMY_TEAM.ARMY_TEAM_DEF : SGCommonProto.E_ARMY_TEAM.ARMY_TEAM_ATK);
                }
            }

            for(SpriteExpeditionBean spriteExpeditionBean : cityBean.getSpriteExpeditionList())
            {
                spriteExpeditionBean.setCurCity(cityBean.id);
                spriteExpeditionBean.setTeam(worldMapData.isAlly(spriteExpeditionBean.getCamp(), cityBean.camp) ? SGCommonProto.E_ARMY_TEAM.ARMY_TEAM_DEF : SGCommonProto.E_ARMY_TEAM.ARMY_TEAM_ATK);
                spriteExpeditionBean.updateBaseInfo();
                spriteExpeditionBean.initBattleTemp();
            }
        }

        int attackCount = 0;
        for(CityBean cityBean : cityMap.values())
        {
            attackCount = 0;
            for(SpritePlayerBean spritePlayerBean : cityBean.getSpritePlayerList())
            {
                if(spritePlayerBean.isAttacker())
                    attackCount++;
            }

            for(SpriteExpeditionBean spriteExpeditionBean : cityBean.getSpriteExpeditionList())
            {
                if(spriteExpeditionBean.isAttacker())
                    attackCount++;
            }

            if(attackCount > 0)
            {
                //攻击方有人，城设置为战斗状态，防御方是肯定有人的，因为会初始化守卫
                cityBean.setStatus(SGCommonProto.E_CITY_STATUS.CITY_STATUS_BATTLE);

                for(SpritePlayerBean spritePlayerBean : cityBean.getSpritePlayerList())
                {
                    //玩家要先进入等待状态
                    spritePlayerBean.setStatus(SGCommonProto.E_ARMY_STATUS.ARMY_STATUS_WAIT);
                }
                for(SpriteExpeditionBean spriteExpeditionBean : cityBean.getSpriteExpeditionList())
                {
                    //远征军直接进入匹配状态
                    spriteExpeditionBean.setStatus(SGCommonProto.E_ARMY_STATUS.ARMY_STATUS_MATCH);
                }
            }
            else
            {
                //城构造方法里已经设置为和平，所以这里不用再设置城的状态为和平，而且城的设置和平还会再初始化守卫，如果这里再设置会重复
                //攻击方没有人,远征军如果还有路线要完成的要继续行走
                for(SpriteExpeditionBean spriteExpeditionBean : cityBean.getSpriteExpeditionList())
                {
                    if(!spriteExpeditionBean.isEndRoute())
                    {
                        //城变为和平，远征军重新设置为移动
                        spriteExpeditionBean.setStatus(SGCommonProto.E_ARMY_STATUS.ARMY_STATUS_MOVE);
                    }
                }
            }
        }
    }


    /**
     * 运行 一秒一次
     * @param currentTime
     */
    public void update(long currentTime)
    {
        for(PlayerController playerController : playerList)
        {
            playerController.update(currentTime);

            if(playerController.isOverdue(currentTime))
            {
                GameServer.getInstance().playerOffline(playerController, true, E_OffLineType.OFFLINE_OVERTIME);
            }
        }

        for(BattleCachePlayer battleCachePlayer : battlePlayerCacheMap.values())
        {
            if(battleCachePlayer.isOverdue())
            {
                removeBattleCachePlayer(battleCachePlayer.getPlayerController().getObjectIndex());
            }
        }

        E_NoticeType noticeType = null;
        //循环发送GM公告
        for(NoticeInfo info : gmNoticeList){
            noticeType = info.getNoticeType();
            if(info.canSendMsg()){
                dispatchGM(info.getContent(),noticeType);
                ServerManager.getInstance().sendNotice(info.getContent(),noticeType);
                GameServer.getInstance().getWorldManager().dispatchChat(SGCommonProto.ChatItem.newBuilder()
                        .setContent(info.getContent()).setChatType(SGCommonProto.E_CHAT_TYPE.CHAT_TYPE_SYSTEM).
                                setSendTime(DataFactory.currentTime).build(),noticeType);
                continue;
            }

            if(info.canDelete()){
                gmNoticeList.remove(info);
            }
        }


        //玩家获得公告管理 30秒后发送
        for(NoticeInfo info : getNoticeList){
            if(currentTime - info.getStartTime() > 30000){
                GameServer.getInstance().getWorldManager().dispatchGet(info.getContent());
                GameServer.getInstance().getWorldManager().dispatchChat(SGCommonProto.ChatItem.newBuilder()
                        .setContent(info.getContent()).setChatType(SGCommonProto.E_CHAT_TYPE.CHAT_TYPE_SYSTEM).
                                setSendTime(DataFactory.currentTime).build());
                getNoticeList.remove(info);
            }
        }

        List<WaitPlayer> removeWaitPlayerList = new CopyOnWriteArrayList<>();
        //取出队列元素，遍历那个时间到了 出队列
        for (WaitPlayer waitPlayer : waitPlayerList)
        {
             if(waitPlayer.isWaitEnd())
             {
                 removeWaitPlayerList.add(waitPlayer);
             }
        }


//        Map<String, BattleTemp> map = null;
//        for(Integer key : spriteBattleTempMap.keySet())
//        {
//            map = spriteBattleTempMap.get(key);
//            for(String index : map.keySet())
//            {
//                if(map.get(index).isOverdue(currentTime))
//                {
//                    LogUtils.debug("战斗历史记录超时 -> " + index);
//                    map.remove(index);
//                }
//            }
//        }

        WorldBossData bossData = WorldInfoFactory.getInstance().getWorldBossData();
        if(bossData.getEndTime() !=0){
            if(DataFactory.currentTime > bossData.getEndTime()){
                bossData.bossOutTime();
            }
        }
        //判断是否有boss奖励
        if (bossData.getDeathTime() != 0l && CoreUtils.getBossBattleTime(bossData.getDeathTime()) < currentTime){
            //有奖励 设置时间为0 并起一个新线程发放奖励
            bossData.setDeathTime(0l);
            GameServer.getInstance().startThread(()->{
                rankRewardRest(SGCommonProto.E_RANK_TYPE.RANK_TYPE_BOSS);
            });
        }
        //遍历所有的拍卖是否结束
        WorldAuctionBean auctionBean;
        Map<String,AuctionRewardPlayer> savePlayerMap = new ConcurrentHashMap<>();
        AuctionConfig auctionConfig = null;
        BoonMsgChannel boonMsgChannel = (BoonMsgChannel) SpringContext.getMessageChannel(BoonMsgChannel.class);
        for (Map.Entry<Integer, WorldAuctionBean> entry : WorldInfoFactory.getInstance().getWorldAuctionData().getAuctionMap().entrySet()) {
            auctionBean = entry.getValue();
            //2.如果没有结束
            if (auctionBean.getState() == E_AuctionStatus.INT_THE_AUCTION.getCode()) {
                //判断是否到时间
                //3.获取配置表中的keepTime
                auctionConfig = WorldAuctionData.getAuctionConfig(auctionBean.getAuctionConfigId());
                if (auctionConfig == null){
                    LogUtils.error("auctionConfigID ->" + auctionBean.getAuctionConfigId());
                    continue;
                }
                if (currentTime >= (auctionBean.getStartTime() + auctionConfig.keepTime)) {
                    //如果当前的时间大于  开始时间  + 持续时间  那么结束
                    //4.判断是否有人出价
                    boonMsgChannel.auctionSuccess(auctionBean, !StringUtils.isNullOrEmpty(auctionBean.getCurrentPlayer()), savePlayerMap);
                }
            }
        }


        WorldMapUpdateResult result = WorldInfoFactory.getInstance().update(currentTime);

        //直接结算的匹配组
        List<MapMatchTeam> directEndMatchTeamList = new CopyOnWriteArrayList<>();

        PlayerController playerController = null, targetController = null;
        BattleInitParamWorldMap param = null;
        SpritePlayerBean spritePlayerBean = null, targetPlayerBean = null;
        String battleId = "";

        ServerInfoBattle serverInfo = ServerManager.getInstance().getFreeBattleServer();
        for(MapMatchTeam mapMatchTeam : result.getStartBattleMatchTeamList())
        {
            if(serverInfo == null)
            {
                LogUtils.error("战斗服务器没有开启!");
                directEndMatchTeamList.add(mapMatchTeam);
            }
            else
            {
                if(mapMatchTeam.getPlayer() instanceof SpritePlayerBean)
                {
                    spritePlayerBean = (SpritePlayerBean) mapMatchTeam.getPlayer();
                    param = new BattleInitParamWorldMap(mapMatchTeam.getMapId(), mapMatchTeam.getCityId(), spritePlayerBean.getMasterPlayerIndex());
                    if(spritePlayerBean.getActionPlayerType() == E_ActionPlayerType.ONLINE_MAP && spritePlayerBean.isInCity())
                    {
                        playerController = spritePlayerBean.getPlayerController();
                        if(playerController == null) playerController = getPlayerController(spritePlayerBean.getObjectIndex());
                        battleId = MsgUtils.startBattle(serverInfo, playerController, SGCommonProto.E_BATTLE_TYPE.BATTLE_TYPE_WORLD_MAP, mapMatchTeam.getBattleDetailType(), mapMatchTeam.getTarget().getObjectIndex(), param);
                    }
                    else
                    {
                        if(mapMatchTeam.getTarget() instanceof SpritePlayerBean)
                        {
                            targetPlayerBean = (SpritePlayerBean) mapMatchTeam.getTarget();
                            if(targetPlayerBean.getActionPlayerType() == E_ActionPlayerType.ONLINE_MAP && targetPlayerBean.isInCity())
                            {
                                targetController = targetPlayerBean.getPlayerController();
                                if(targetController == null) targetController = getPlayerController(targetPlayerBean.getObjectIndex());
                                battleId = MsgUtils.startBattle(serverInfo, targetController, SGCommonProto.E_BATTLE_TYPE.BATTLE_TYPE_WORLD_MAP, E_BattleDetailType.PVP_DATA_WORLD_MAP, mapMatchTeam.getPlayer().getObjectIndex(), param);
                            }
                            else
                            {
                                directEndMatchTeamList.add(mapMatchTeam);
                            }
                        }
                        else
                        {
                            directEndMatchTeamList.add(mapMatchTeam);
                        }
                    }
                }
                else
                {
                    directEndMatchTeamList.add(mapMatchTeam);
                }
            }

            mapMatchTeam.battleStatus();

            if(!Utils.isNullOrEmpty(battleId))
                RecordManager.getInstance().addWorldMapBattleStartRecord(battleId, mapMatchTeam);
        }

        List<Player> offlinePlayerList = new ArrayList<>();

        for(MapMatchTeam mapMatchTeam : directEndMatchTeamList)
        {
            WorldMapUtils.directEndMapBattle(mapMatchTeam.getPlayer(), mapMatchTeam.getTarget(), mapMatchTeam.getCityId(), offlinePlayerList);
        }

        if(!result.getOccupyCityMap().isEmpty())
        {
            //TwoTuple<Player, PlayerController> playerResult = null;
            CommonData commonData = null;
            Player player = null;
            for(Map.Entry<Integer, OccupyCityParam> entry : result.getOccupyCityMap().entrySet())
            {
                if(entry.getValue().getWinner() instanceof SpritePlayerBean)
                {
                    spritePlayerBean = (SpritePlayerBean) entry.getValue().getWinner();

                    player = spritePlayerBean.getPlayer();
                    if (player == null){
                        LogUtils.error("worldMap battle end winner is not existence playerIndex -> " + spritePlayerBean.getObjectIndex());
                        continue;
                    }

                    updateWorldMapTaskComplete(player, commonData = new CommonData(SGCommonProto.E_WORLDMAPTASK_TYPE.WORLD_MAP_TASK_KILL_CITY.getNumber(), 1));

                    /**
                     * 争霸赛夺城
                     */
                    CityConfig cityConfig = DataFactory.getInstance().getGameObject(DataFactory.CITY_KEY, entry.getKey());
                    HegemonyScoreChangeBean changeBean = player.getWorldMapKillData().captureCity(SGCommonProto.E_CITY_TYPE.forNumber(cityConfig.type));

                    if(spritePlayerBean.getPlayerController() == null)
                    {
                        //玩家离线
                        offlinePlayerList.add(player);
                    }
                    else
                    {
                        MsgUtils.sendWorldMapTaskChange(spritePlayerBean.getPlayerController(), commonData);
                        SendUtils.sendChangeData(0, spritePlayerBean.getPlayerController());
                        SendUtils.sendHegemoneyChange(spritePlayerBean.getPlayerController(), changeBean);
                    }
                }

                RecordManager.getInstance().getInstance().addWorldMapOccupyRecord(entry.getKey(), entry.getValue());
            }
        }

        for(SpritePlayerBean spritePlayer : result.getRecoverPlayerList())
        {
            if(!spritePlayer.getBattleTemp().isFull())
            {
                //要设置成恢复状态
                WorldMapUtils.initRecover(spritePlayer, true);
            }
        }

        CityBean cityBean = null;
        WorldMapData worldMapData = null;
        for(Map.Entry<Integer, List<SpritePlayerBean>> entry : result.getRemovePlayerMap().entrySet())
        {
            //玩家离开大地图 超过十分钟清除
            for(SpritePlayerBean spritePlayer : entry.getValue())
            {
                worldMapData = WorldInfoFactory.getInstance().getWorldMapData(spritePlayer.getMasterPlayerIndex());
                cityBean = worldMapData.getCity(entry.getKey());
                if(cityBean != null)
                {
                    if(spritePlayer.getPlayerController() != null) {
                        WorldMapUtils.hegemonyLose(spritePlayer);
                    }
                    else if(spritePlayer.getBasePlayer() != null) {
                        WorldMapUtils.hegemonyLose(spritePlayer);
                        offlinePlayerList.add(spritePlayer.getPlayer());
                    }
                    worldMapData.removeSprite(spritePlayer, cityBean, true, E_CityInOutType.OUT_TIMEOUT);
                    cityBean.checkCityStatus(spritePlayer);
                }
            }
        }

        for(Map.Entry<Integer, List<SpriteExpeditionBean>> entry : result.getRemoveExpeditionMap().entrySet())
        {
            //只有世界大地图才有远征军
            cityBean = WorldInfoFactory.getInstance().getWorldMapData().getCity(entry.getKey());
            if(cityBean != null)
            {
                for(SpriteExpeditionBean spriteExpeditionBean : entry.getValue())
                {
                    WorldInfoFactory.getInstance().getWorldMapData().removeSprite(spriteExpeditionBean, cityBean, true, E_CityInOutType.OUT_EXPEDITION_TIMEOUT);
//                    LogUtils.debug("删除到期远征军,并且重新检测城状态 -> " + spriteExpeditionBean + " cityId:" + cityBean.id);
                    cityBean.checkCityStatus(spriteExpeditionBean);
                }

                RecordManager.getInstance().addExpedition(cityBean.getConfig().name + "(" + cityBean.id + ")", entry.getValue().get(0).getName(), "Remove Expedition:" + entry.getValue() + ",cityStatus:" + cityBean.getStatus());
            }
        }


        for(WaitPlayer waitPlayer : removeWaitPlayerList)
        {
            if(waitPlayer.isOpenConnection()){
                waitPlayer.login();
            }
            synchronized(NettyTCPServerHandler.class){
                removeWaitPlayer(waitPlayer.getAccount());
            }
        }

        auctionPlayerUpdate(savePlayerMap);

        GameServer.getInstance().savePlayerList(offlinePlayerList, true, ChallengeInfo.class, TaskInfo.class, SettingInfo.class, BagInfo.class);
    }


    public void checkFlush(Calendar calendar)
    {
        flushBoss(calendar);

        flushCityDrop(calendar);

        flushExpedition(calendar);
    }

    private void flushExpedition(Calendar calendar)
    {
        List<CityExpeditionConfig> list = DataFactory.getInstance().getDataList(DataFactory.CITY_EXPEDITION_KEY);
        if(list != null)
        {
            RouteConfig routeConfig = null;
            List<CityArmyConfig> tempList = DataFactory.getInstance().getDataList(DataFactory.CITY_ARMY_KEY);
            List<CityArmyConfig> armyList = new ArrayList<>();
            for(CityArmyConfig cityArmyConfig : tempList)
            {
                if(cityArmyConfig.grade == ConstantFactory.CITY_ARMY_GRADE_WORLD)
                {
                    armyList.add(cityArmyConfig);
                }
            }
            for(CityExpeditionConfig expeditionConfig : list)
            {
                if(TimeUtils.isArriveTime(expeditionConfig.startTime, calendar,GameServer.startTime))
                {
                    for(CommonData commonData : expeditionConfig.routes)
                    {
                        routeConfig = DataFactory.getInstance().getGameObject(DataFactory.ROUTE_KEY, commonData.value);
                        CityBean cityBean = WorldInfoFactory.getInstance().getWorldMapData().getCity(routeConfig.cityList[0]);
                        for(CityArmyConfig armyConfig : armyList)
                        {
                            if(armyConfig.type == expeditionConfig.armyType && commonData.id == armyConfig.camp)
                            {
                                int lv = cityBean.initExpedition(armyConfig, expeditionConfig, routeConfig.cityList);
                                RecordManager.getInstance().addExpedition(cityBean.getConfig().name + "(" + cityBean.id + ")", armyConfig.name + "(Lv" + lv + ")",
                                        "Create Expedition,count:" + expeditionConfig.count + ",camp:" + commonData.id + ",keepTime:" + expeditionConfig.startTime.getKeepTime(TimeUtils.MINUTE) + "m,route:" + Arrays.toString(routeConfig.cityList));
                                break;
                            }
                        }
                    }
                }
            }
        }
    }


    private void flushCityDrop(Calendar calendar){
        List<CityDropGroupConfig> dropGroupConfigList = DataFactory.getInstance().getDataList(DataFactory.CITY_DROP_GROUP);
        WorldMapData worldMapData = WorldInfoFactory.getInstance().getWorldMapData();
        for (CityDropGroupConfig dropConfig:dropGroupConfigList){
            if (dropConfig.type != E_CityDrop_Flush_Type.CITY_DROP_FLUSH_TIME.getCode())
                continue;
            if (TimeUtils.isArriveTime(dropConfig.timeSubType, calendar,GameServer.startTime)){
                worldMapData.cityDrop(dropConfig, null, null);
            }
        }
    }

    private void flushBoss(Calendar calendar)
    {
        WorldBossData worldBossData = GameServer.getInstance().getWorldBossData();
        //检测是否有boss刷新
        List<WorldBossConfig> configs = DataFactory.getInstance().getDataList(DataFactory.WORLD_BOSS_KEY);
        WorldBossConfig bossConfig = null;
        if(configs != null){
            for(WorldBossConfig config : configs){
                if(TimeUtils.isArriveTime(config.freshTime,calendar,GameServer.startTime)){
                    bossConfig = config;
                    break;
                }
            }
            if(bossConfig != null){
                if(worldBossData.isCanCreeateBoss()){
                    //暂时用大地图的平均玩家等级,下个版本单独记录在一个地方
                    if(worldBossData.createNewBoss(bossConfig.id, WorldInfoFactory.getInstance().getWorldBossData().getAverageLv())){
                        GameServer.getInstance().getWorldManager().addNotice(
                                new NoticeInfo(WordFactory.getWord(WordFactory.BOSS_FRESH_NOTICE, bossConfig.name), 5, 10,
                                        "system", DataFactory.currentTime,E_NoticeType.NOTICE_TYPE_BOSS));
                        //创建boss成功后要更新排行榜
                        WorldRankData rankData = WorldInfoFactory.getInstance().getWorldRankData();
                        RecordManager.getInstance().addLastRankMap(SGCommonProto.E_RANK_TYPE.RANK_TYPE_BOSS, rankData.getRankList(SGCommonProto.E_RANK_TYPE.RANK_TYPE_BOSS));
                        rankData.clearRank(SGCommonProto.E_RANK_TYPE.RANK_TYPE_BOSS);

                        GameServer.getInstance().startThread(() -> {
                            for(PlayerController playerController : playerList)
                            {
                                SendUtils.sendRedPointRemind(playerController, SGCommonProto.E_RED_POINT_TYPE.RED_POINT_TYPE_WORLD_BOSS);
                            }
                        });
                    }
                }
            }
        }
    }

//    private void bossRankReward(){
//        List<WorldRankBean> list = WorldInfoFactory.getInstance().getWorldRankData().getRankList(SGCommonProto.E_RANK_TYPE.RANK_TYPE_BOSS);
//
//    }

    /**
     * 调用此方法 变更完成度
     * @param player
     * @param worldMapTaskData
     * @param type
     * @param l
     */
    public static void upadteWorldMapTaskComplete(Player player,WorldMapTaskData worldMapTaskData,SGCommonProto.E_WORLDMAPTASK_TYPE type,long l){
        worldMapTaskData = player.getWorldMapTaskData();
        int beforeValue = worldMapTaskData.getMilitaryExploitValue();
        worldMapTaskData.addCompleted(type,l);
        int afterValue = worldMapTaskData.getMilitaryExploitValue();
        if(beforeValue != afterValue)
            GameServer.getInstance().getWorldManager().updateRankInfo(SGCommonProto.E_RANK_TYPE.RANK_TYPE_WORLDMAP,player,afterValue);
    }

    public static void updateWorldMapTaskComplete(Player player, CommonData... commonDatas){
        WorldMapTaskData worldMapTaskData = player.getWorldMapTaskData();
        int beforeValue = worldMapTaskData.getMilitaryExploitValue();
        worldMapTaskData.addCompleted(commonDatas);
        int afterValue = worldMapTaskData.getMilitaryExploitValue();
        if(beforeValue != afterValue)
            GameServer.getInstance().getWorldManager().updateRankInfo(SGCommonProto.E_RANK_TYPE.RANK_TYPE_WORLDMAP, player,afterValue);
    }

    public void auctionPlayerUpdate(Map<String,AuctionRewardPlayer> savePlayerMap){
        if(savePlayerMap.size() > 0)
        {
            //遍历map
            List<Player> savePlayerList = new ArrayList<>();
            TwoTuple<Player,PlayerController> twoTuple;
            Player player;
            for(Map.Entry<String,AuctionRewardPlayer> entry:savePlayerMap.entrySet()){
                twoTuple =  GameServer.getInstance().getWorldManager().getPlayerResult(entry.getKey());

                player = twoTuple.getFirst();
                if(player == null){
                    continue;
                }
                player.getBonusData().addAuctionReward(entry.getValue().getTotalRewardMoney());
                if(entry.getValue().getRewardMailList() != null && entry.getValue().getRewardMailList().size() > 0){
                    for (MailDB mailDB:entry.getValue().getRewardMailList()){
                        MailInfo mailInfo = twoTuple.getFirst().getExtInfo(MailInfo.class);
                        mailInfo.addMail(SGCommonProto.E_MAIL_TYPE.MAIL_TYPE_SYSTEM_VALUE, mailDB);
                    }
                }

                if(twoTuple.getSecond() == null) {
                    savePlayerList.add(player);
                }else{
                    //增加拍卖行花钱后的砖石立马缓存到玩家的当日累计消耗
                    player.getBonusData().addDiamondsCache(entry.getValue().getCacaheMoney());
                }
            }

            GameServer.getInstance().savePlayerList(savePlayerList, false, BoonInfo.class, MailInfo.class);
        }
    }


    /**
     * 玩家进入游戏世界
     * @param playerController
     */
    public synchronized void playerEnterGame(PlayerController playerController)
    {
        PlayerController tempPlayerController = getPlayerController(playerController.getObjectIndex());
        if(tempPlayerController != null)
        {
            playerList.remove(tempPlayerController);
            playerIndexMap.remove(tempPlayerController.getObjectIndex());
        }

        LogUtils.info("玩家:" + playerController.getObjectIndex() + " -> " + playerController.getName() + " 进入游戏!");

        playerList.add(playerController);

        playerIndexMap.put(playerController.getObjectIndex(), playerController);

        GameServer.getInstance().getWorldManager().updateRankInfo(SGCommonProto.E_RANK_TYPE.RANK_TYPE_FC, playerController.getPlayer(), playerController.getPlayer().fc);

//        if(WorldInfoFactory.getInstance().updateServerStatus(playerList.size()))
//        {
//            GameServer.getInstance().notifyServerStatus(null);
//        }

        MainFrame.updatePlayerCount();
    }


    public synchronized void playerExitGame(PlayerController playerController, E_OffLineType type)
    {
        LogUtils.info("玩家:" + playerController.getObjectIndex() + " -> " + playerController.getName() + " 离开游戏!类型->" + type.getMsg());

//        if(playerController.getBattleData() == null)
//        {
//            //不在战斗中，删除
//            removeBattleCachePlayer(playerController.getObjectIndex());
//        }

        playerController.destroy();

        reduceCachePlayer();

        WorldMapData worldMapData = WorldInfoFactory.getInstance().getWorldMapData(playerController);
        if(worldMapData != null){
//            SpritePlayerBean spritePlayerBean = worldMapData.getPlayerActionBean(playerController.getObjectIndex());
//            if (type.equals(E_OffLineType.OFFLINE_OVERTIME) && spritePlayerBean != null){
//                //玩家超时被T下线清除玩家数据
//                WorldMapUtils.hegemonyLose(spritePlayerBean);
//                LogUtils.warn("player:" + playerController.getName() + " " + type + " 清除争霸赛数据!");
//            }
            worldMapData.playerOffline(playerController.getPlayer());
        }
//        //玩家离线保存在线时间
//        OnlineRewardData onlineRewardData = playerController.getPlayer().getOnlineData();
//        onlineRewardData.updateOnlineRewardTime();

        playerList.remove(playerController);

        playerIndexMap.remove(playerController.getObjectIndex());

//        if(WorldInfoFactory.getInstance().updateServerStatus(playerList.size()))
//        {
//            GameServer.getInstance().notifyServerStatus(null);
//        }

        cancelWaitQueue(playerController.getPlayer().getAccount());

        MainFrame.updatePlayerCount();

    }

    public void cancelWaitQueue(String account) {
        WaitPlayer waitPlayer = getWaitPlayer(account);
        WaitPlayer next = null;
        if(waitPlayer != null){
            int index = waitPlayerList.indexOf(waitPlayer);
            int size = waitPlayerList.size();
            for(int i = index; i< size; i++){
                next = waitPlayerList.get(i);
                next.setEndTime(i * ConfigFactory.gmSetting.getPlayerWaitTime() + DataFactory.currentTime);
                try {
                    MsgUtils.sendLoginFail( waitPlayer.getLoginHandler().getConnection(), next.getWaitTime());
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
            removeWaitPlayer(waitPlayer.getAccount());
        }
    }

    public TwoTuple<Player, PlayerController> getPlayerByName(String name)
    {
        TwoTuple<Player, PlayerController> result = null;
        PlayerController playerController = getPlayerControllerByName(name);
        if(playerController != null)
        {
            result = new TwoTuple<>(playerController.getPlayer(), playerController);
        }
        else
        {
            PlayerService playerService = SpringContext.getBean(PlayerService.class);
            PlayerModel playerModel = playerService.getPlayerByName(name);
            if(playerModel == null)
                result = new TwoTuple<>();
            else
                result = new TwoTuple<>(new Player(playerModel));
        }

        return result;
    }

    public TwoTuple<Player, PlayerController> getPlayerResult(String playerIndex)
    {
        TwoTuple<Player, PlayerController> result = null;
        PlayerController playerController = getPlayerController(playerIndex);
        if(playerController != null)
        {
            result = new TwoTuple<>(playerController.getPlayer(), playerController);
        }
        else
        {
            PlayerService playerService = SpringContext.getBean(PlayerService.class);
            PlayerModel playerModel = playerService.getPlayerByIndex(playerIndex);
            if(playerModel == null)
                result = new TwoTuple<>();
            else
                result = new TwoTuple<>(new Player(playerModel));
        }

        return result;
    }

    public Map<String,Player> getPlayerMap(List<WorldRankBean> worldRankBeanList){
        List<String> indexList = new ArrayList<>();
        for (WorldRankBean rankBean:worldRankBeanList){
            indexList.add(rankBean.getObjectIndex());
        }
        return getPlayerMap(indexList);
    }

    public List<Player> getPlayerList(List<WorldRankBean> worldRankBeanList){
        List<String> indexList = new ArrayList<>();
        for (WorldRankBean rankBean:worldRankBeanList){
            indexList.add(rankBean.getObjectIndex());
        }
        return getPlayerList(indexList);
    }

    public List<Player> getPlayerList(Collection<String> indexList){
        List<Player> playerList = new ArrayList<>();
        PlayerController playerController = null;
        PlayerService playerService = SpringContext.getBean(PlayerService.class);
        for (String objectIndex:indexList){
            playerController = getPlayerController(objectIndex);
            if(playerController != null){
                playerList.add(playerController.getPlayer());
            }else{
                playerList.add(new Player(playerService.getPlayerByIndex(objectIndex)));
            }
        }
        return playerList;
    }

    /**
     * 根据玩家的流水号集合 获取玩家的map key为流水号方便查找 不需要遍历
     * @param indexList
     * @return
     */
    public Map<String,Player> getPlayerMap(Collection<String> indexList){
        Map<String,Player> playerMap = new HashMap<>();
        PlayerController playerController = null;
        List<String> offLineList = new ArrayList<>();
        for (String objectIndex:indexList){
            playerController = getPlayerController(objectIndex);
            if(playerController != null){
                playerMap.put(objectIndex,playerController.getPlayer());
            }else{
                offLineList.add(objectIndex);
            }
        }
        //如果有离线玩家需要进数据库进行查找
        if(!offLineList.isEmpty()){
            PlayerService playerService = SpringContext.getBean(PlayerService.class);
            List<PlayerModel> playerModelList = playerService.getPlayerListByIndex(offLineList);
            for (PlayerModel playerModel:playerModelList){
                playerMap.put(playerModel.getObjectIndex(),new Player(playerModel));
            }
        }
        return playerMap;
    }

    /**
     * 从数据库查找得到所有的玩家
     * @return
     */
    public List<Player> getAllPlayerList(){
        PlayerService playerService = SpringContext.getBean(PlayerService.class);
        List<Player> allPlayer = new ArrayList<>();
        List<PlayerModel> list = playerService.getAllPlayerList();
        LogUtils.info("开始loadPlayer 共："+ list.size());
        int i= 0;
        for (PlayerModel playerModel:list){
            allPlayer.add(new Player(playerModel));
            System.out.println("执行完成第 " + (++i) + "个");
        }
        return allPlayer;
    }

    public Map<String,Player> getAllPlayerMap(){
        //PlayerService playerService = SpringContext.getBean(PlayerService.class);
        Map<String ,Player> allPlayer = new HashMap<>();
        //List<PlayerModel> list = playerService.findAll();

        ReadPlayerMapper readPlayerMapper = SpringContext.getBean(ReadPlayerMapper.class);
        List<PlayerModel> list = readPlayerMapper.findAll();
        for (PlayerModel playerModel:list){
            allPlayer.put(playerModel.getObjectIndex(), new Player(playerModel));
        }
        return allPlayer;
    }

    public Map<String, Object> getNameAvatarInfo(String playerIndex)
    {
        PlayerService playerService = SpringContext.getBean(PlayerService.class);

        return playerService.getNameAvatarInfo(playerIndex);
    }

    public void addGM(NettyConnection connection)
    {
        if(connection == null || !(connection.getObject() instanceof GMModel))
            return;

        gmList.add(connection);
    }

    public void delGM(NettyConnection connection)
    {
        gmList.remove(connection);
    }

    public PlayerController getBattleCachePlayer(String playerIndex)
    {
        BattleCachePlayer battleCachePlayer = battlePlayerCacheMap.get(playerIndex);
        return battleCachePlayer != null ? battleCachePlayer.getPlayerController() : null;
    }

    public void addBattleCachePlayer(PlayerController playerController)
    {
        battlePlayerCacheMap.put(playerController.getObjectIndex(), new BattleCachePlayer(DataFactory.currentTime, playerController));
    }

    public void removeBattleCachePlayer(String playerIndex)
    {
        battlePlayerCacheMap.remove(playerIndex);
    }

    public PlayerController getPlayerController(String playerIndex){
        if(playerIndex == null)
            return null;

        return playerIndexMap.get(playerIndex);
    }

    /**
     * 获取所有在线玩家
     * @return
     */
    public Map<String,PlayerController> getAllOnLinePlayerController(){
        return playerIndexMap;
    }

    public PlayerController getPlayerControllerByName(String playerName){
        for(PlayerController playerController : playerList)
        {
            if(playerController.getName().equals(playerName))
                return playerController;
        }
        return null;
    }

    public PlayerController getPlayerControllerByUid(int uid){
        for(PlayerController playerController : playerList)
        {
            if(playerController.getPlayer().getUid() == uid)
                return playerController;
        }
        return null;
    }

    public PlayerController getPlayerControllerByAccount(String account)
    {
        for(PlayerController playerController : playerList)
        {
            if(account.startsWith("QUICK") && playerController.getPlayer().getDeviceId() != null)
            {
                if(playerController.getPlayer().getDeviceId().equals(account))
                    return playerController;
            }
            else
            {
                if(playerController.getPlayer().getAccount().equals(account))
                    return playerController;
            }
        }
        return null;
    }


    public List<PlayerController> getPlayerList() {
        return playerList;
    }

    public int getPlayerCount()
    {
        return playerList.size();
    }

    public int getConnectionCount()
    {
        return connections.size();
    }


    public void addConnection(NettyConnection connection)
    {
        connections.add(connection);
//        LogUtils.info("添加连接 -> " + connection.getId() + "  添加之后数量 -> " + connections.size());

        MainFrame.updatePlayerCount();
    }

    public void removeConnection(NettyConnection connection)
    {
//        LogUtils.info("删除连接 -> " + connection.getId() + "  删除之前数量 -> " + connections.size());
        connections.remove(connection);
//        LogUtils.info("删除连接 -> " + connection.getId() + "  删除之后数量 -> " + connections.size());

        MainFrame.updatePlayerCount();
    }

    public List<NettyConnection> getConnections() {
        return connections;
    }

    public void addNotice(NoticeInfo info){
        if(info != null && info.checkParam()){
            gmNoticeList.add(info);
        }
    }

    public void delNotice(String id)
    {
        for(NoticeInfo noticeInfo : gmNoticeList)
        {
            if(noticeInfo.getId().equals(id))
            {
                gmNoticeList.remove(noticeInfo);
                break;
            }
        }
    }

    public List<NoticeInfo> getGmNoticeList() {
        return gmNoticeList;
    }

    public List<NoticeInfo> getGetNoticeList() {
        return getNoticeList;
    }

    public void addGroupMail(MailGroup mailGroup)
    {
        mailGroupList.add(mailGroup);
    }

    public List<MailGroup> getMailGroupList()
    {
        return mailGroupList;
    }


    public int getOnlinePlayerCount()
    {
        return currentPlayerCount;
    }

    /**
     * 是否爆满
     * @return
     */
    public boolean isFull()
    {
//        LogUtils.info("当前在线人数: " + getOnlinePlayerCount() + "，排队人数：" + waitPlayerList.size());
        return (getOnlinePlayerCount() + waitPlayerList.size()) >= WorldInfoFactory.getInstance().getFullCount();
    }

    /**
     * 是否需要排队
     * @return
     */
    public boolean isNeedQueueWait()
    {
        int count = getOnlinePlayerCount();
//        LogUtils.debug("当前排队人数：" + count);
        return count >= WorldInfoFactory.getInstance().getCrowdCount();
    }

    public WaitPlayer getWaitPlayer(String account)
    {
        return waitPlayerMap.get(account);
    }

    public void removeWaitPlayer(String account)
    {
        WaitPlayer removePlayer = waitPlayerMap.get(account);
        if(removePlayer != null)
        {
            waitPlayerList.remove(removePlayer);
            waitPlayerMap.remove(account);
        }
    }

    public int getWaitPlayerCount()
    {
        return waitPlayerList.size();
    }

    public void addWaitPlayer(String account, int waitTime, NettyTCPServerHandler loginHandler, ByteBuf param)
    {
        if(getWaitPlayer(account) != null)
            return;

        WaitPlayer waitPlayer = new WaitPlayer(account, waitTime + DataFactory.currentTime, loginHandler, param);
        waitPlayerList.add(waitPlayer);
        waitPlayerMap.put(account, waitPlayer);
    }

    /**
     * 检测其他地方登录
     * @param username
     */
    public void checkLoginOther(String username) {
        if(!StringUtils.isNullOrEmpty(username)){
            GMModel gmModel;
            for(NettyConnection connection : gmList){
                if(connection.getObject() instanceof GMModel){
                    gmModel = (GMModel) connection.getObject();
                    if(username.equals(gmModel.getUsername())){
                        connection.sendMsg(CodeFactory.GM_LOGIN_OTHER);
                        connection.destroy();
                    }
                }
            }
        }

    }



    public static void saveDiamonds(String playerIndex,int count){
        DiamondsChangeService diamondsChangeService = SpringContext.getBean(DiamondsChangeService.class);
        diamondsChangeService.insert(new DiamondsChangeModel(
                new Date(),
                playerIndex,
                count > 0? -count:count
        ));
    }


    /**
     * 获取玩家的钻石消耗缓存
     */
    public Map<E_QueryRechargeCountType,Integer> getDiamondsCache(boolean first,Player player){
        DiamondsChangeService diamondsChangeService = SpringContext.getBean(DiamondsChangeService.class);
        /**
         * 1. 获取内存中未进行数据库保存的 value
         * 2. 获取今日充值缓存 如果是今天首次登陆的话 不需要读数据库获取缓存 value
         * 3. 读取配置表获取充值缓存 + value
         * 4. 添加到BonusData的diamondsCache
         */
        Map<E_QueryRechargeCountType,Integer> diamondsMap = new ConcurrentHashMap<>();

        int cacheDiamonds = 0;
        for (PlayerGoodsChange goodChange : RecordManager.getInstance().getGoodsChangeList())
        {
            if (player.getObjectIndex().equals(goodChange.getPlayerIndex())){
                if(goodChange.getGoodsType() == SGCommonProto.E_GOODS_TYPE.GOODS_TYPE_ASSETS_VALUE
                        && goodChange.getId() == ConfigFactory.ASSET_MONEY_KEY && goodChange.getCount() < 0){
                    cacheDiamonds += goodChange.getCount();
                }
            }
        }

        int diamonds = cacheDiamonds;
        //1 今日
        // 数据库中存的钻石消耗为负数 所以这里要取相反数
        TwoTuple<Long, Long> twoTuple;
        //first true表示今天不是第一次登陆 false是第一次登陆
        if(first){
            twoTuple = CoreUtils.getInDayTime();
            diamonds += diamondsChangeService.getCountByTime(player.getObjectIndex(),twoTuple.getFirst(),twoTuple.getSecond());
        }
        diamondsMap.put(E_QueryRechargeCountType.DAILY,-diamonds);
        //2 自定义
        TimeLimitedActivitiesConfig timeLimitedActivitiesConfig = TimeLimitedActivitiesConfig.getCurrentConfigByType(E_TimeLimitActivityType.TOTAL_DIAMONDS);
        diamonds = cacheDiamonds;
        if(timeLimitedActivitiesConfig != null){
            twoTuple = CoreUtils.getMinAndMaxTime(timeLimitedActivitiesConfig.getMinDateInt(), timeLimitedActivitiesConfig.getMaxDateInt());
            diamonds += diamondsChangeService.getCountByTime(player.getObjectIndex(),twoTuple.getFirst(),twoTuple.getSecond());
        }
        diamondsMap.put(E_QueryRechargeCountType.DEFINE, -diamonds);

        return diamondsMap;
    }

    /**
     * 转发所有的聊天信息
     * @param
     */
    public void dispatchChat(SGCommonProto.ChatItem chatItem, E_NoticeType... noticeType)
    {
        LogUtils.debug("分发聊天消息:" + chatItem.getContent());
        RecordManager.getInstance().addChat(chatItem);
        for(PlayerController playerController : playerList)
        {
            if (noticeType != null && noticeType.length > 0){
                if (noticeType[0].equals(E_NoticeType.NOTICE_TYPE_BOSS)){
                    //如果是boss推送 判断用户是否开启boss战
                    //如果等级不够不推送
                    if (!CoreUtils.isFunctionUnLock(FunctionFactory.WORLD_BOSS, playerController.getPlayer())){
                        continue;
                    }
                }
            }
            if(chatItem.getChatType() == SGCommonProto.E_CHAT_TYPE.CHAT_TYPE_CAMP) {
                if (chatItem.getCampValue() == playerController.getPlayer().camp) {
                    playerController.sendChat(chatItem);
                }
            }else {
                playerController.sendChat(chatItem);
            }

        }
    }



    public void updateRankPlayerDetail(Player player)
    {
        RankPlayerDetail rankPlayerDetail = rankPlayerDetailMap.get(player.getObjectIndex());
        if(rankPlayerDetail != null)
        {
            rankPlayerDetail.update(player);
        }
        else
        {
            rankPlayerDetail = new RankPlayerDetail(player);
            rankPlayerDetail.setServerName(WorldInfoFactory.getInstance().getName());
            rankPlayerDetailMap.put(player.getObjectIndex(), rankPlayerDetail);
        }
    }

    public void updateRankPlayerDetail(PlayerModel player)
    {
        RankPlayerDetail rankPlayerDetail = rankPlayerDetailMap.get(player.getObjectIndex());
        if(rankPlayerDetail != null)
        {
            rankPlayerDetail.update(player);
        }
        else
        {
            rankPlayerDetail = new RankPlayerDetail(player);
            rankPlayerDetail.setServerName(WorldInfoFactory.getInstance().getName());
            rankPlayerDetailMap.put(player.getObjectIndex(), rankPlayerDetail);
        }
    }

    /**
     * 更新排行(要重新计算排名)
     * @param rankType
     * @param player
     * @param value
     */
    public void updateRankInfo(SGCommonProto.E_RANK_TYPE rankType, Player player, int value)
    {
        boolean updateResult = WorldInfoFactory.getInstance().getWorldRankData().updateRankInfo(rankType, player.getObjectIndex(), value);

        if(updateResult || rankType == SGCommonProto.E_RANK_TYPE.RANK_TYPE_MAPCURRWEEK)
            updateRankPlayerDetail(player);
    }

    /**
     * 更新排行(要重新计算排名)
     * @param rankType
     * @param player
     * @param value
     */
    public void updateRankInfo(SGCommonProto.E_RANK_TYPE rankType, PlayerModel player, int value)
    {
        boolean updateResult = WorldInfoFactory.getInstance().getWorldRankData().updateRankInfo(rankType, player.getObjectIndex(), value);

        if(updateResult)
            updateRankPlayerDetail(player);
    }

    /**
     * 每小时检测争霸赛开放变化
     * @param hour
     */
    public void resetHegemonyInfo(int hour){
        WorldMapData worldMapData = WorldInfoFactory.getInstance().getWorldMapData();
        int lastHour = hour - 1;
        if (lastHour == -1){
            lastHour = 23;
        }
        if (worldMapData.hegemonyIsSettle(hour)){
            //如果在争霸赛开放时间 判断上个小时不在争霸赛开放时间则通知所有玩家 开放
            if (!worldMapData.hegemonyIsSettle(lastHour))
                worldMapData.sendHegemonyChange(true);
        }else{
            //如果不在争霸赛时间 判断上个小时在争霸赛时间通知玩家 关闭
            if (worldMapData.hegemonyIsSettle(lastHour))
                worldMapData.sendHegemonyChange(false);
        }
    }

    public List<WorldRankBean> getRankList(SGCommonProto.E_RANK_TYPE rankType)
    {
        return WorldInfoFactory.getInstance().getWorldRankData().getRankList(rankType);
    }

    public SGCommonProto.E_MAP_HEGEMONY_RANK_TYPE getRankStatus(SGCommonProto.E_RANK_TYPE type){
        return WorldInfoFactory.getInstance().getWorldRankData().getRankStatus(type);
    }

    public WorldRankBean getRankByIndex(SGCommonProto.E_RANK_TYPE rankType,int index){
        return WorldInfoFactory.getInstance().getWorldRankData().getRankByIndex(rankType, index);
    }

    public int getRankByPlayer(Player player,SGCommonProto.E_RANK_TYPE type){
        return WorldInfoFactory.getInstance().getWorldRankData().getRankByPlayer(player, type);
    }

    public RankPlayerDetail getRankPlayer(String playerIndex)
    {
        return rankPlayerDetailMap.get(playerIndex);
    }

    public void removeRankPlayerDetail(Player player)
    {
        rankPlayerDetailMap.remove(player.getObjectIndex());
    }

    public void addPlayerBattleTemp(int battleType, String playerIndex, BattleTemp battleTemp)
    {
        Map<String, BattleTemp> map = spriteBattleTempMap.get(battleType);
        if(map == null)
        {
            map = new ConcurrentHashMap<>();
            spriteBattleTempMap.put(battleType, map);
        }

        if(battleTemp.getMaster().getHp() <= 0 || battleTemp.getSoldierList().size() == 0)
            map.remove(playerIndex);
        else
        {
//            battleTemp.setAddTime(DataFactory.currentTime);
            map.put(playerIndex, battleTemp);
        }
    }

    public BattleTemp getSpriteBattleTemp(int battleType, String objectIndex, String... masterPlayerIndex)
    {
        if(SGCommonProto.E_BATTLE_TYPE.BATTLE_TYPE_WORLD_BOSS_VALUE == battleType && CoreUtils.isNullOrEmpty(objectIndex))
        {
            //playerIndex表示获取BOSS的血
            return WorldInfoFactory.getInstance().getWorldBossData().getBossInfo();
        }
        else if(SGCommonProto.E_BATTLE_TYPE.BATTLE_TYPE_WORLD_MAP_VALUE == battleType)
        {
            WorldMapData worldMapData = WorldInfoFactory.getInstance().getWorldMapData(masterPlayerIndex);
            SpriteBean spriteBean = worldMapData.getSpriteBean(objectIndex);
            if(spriteBean != null)
                return spriteBean.getBattleTemp();
        }

        Map<String, BattleTemp> map = spriteBattleTempMap.get(battleType);
        return map == null ? null : map.get(objectIndex);
    }

    public void clearPlayerBattleTemp(int battleType, String playerIndex)
    {
        Map<String, BattleTemp> map = spriteBattleTempMap.get(battleType);
        if(map != null)
            map.remove(playerIndex);
    }

    public void clearPlayerBattleTemp(int battleType)
    {
        spriteBattleTempMap.remove(battleType);
    }


    public List<NettyConnection> getGmList() {
        return gmList;
    }

    /**
     * 阵营战排行奖励特殊处理
     */
    public boolean rankRewardRest(List<RankPlayer> rankPlayerList){
        try {
            Integer maxValue = 0;
            TwoTuple<List<RankRewardConfig>, Integer> twoTuple = RankRewardConfig.getConfigListByType(SGCommonProto.E_RANK_TYPE.RANK_TYPE_CAMP, maxValue);
            List<RankRewardConfig> configList = twoTuple.getFirst();
            maxValue = twoTuple.getSecond();
            List<WorldRankBean> ranks = new ArrayList<>();
            for (RankPlayer rankPlayer : rankPlayerList) {
                //如果没有领取过奖励
                if (ranks.size() < maxValue && !rankPlayer.isReward())
                    ranks.add(new WorldRankBean(rankPlayer.getObjectIndex()));
            }

            if (ranks.isEmpty()) {
                return false;
            }

            maxValue = ranks.size();
            int first = 0;
            RankRewardConfig config;

            Map<String, AuctionRewardPlayer> savePlayerMap = new HashMap<>();
            for (int i = 0; i < configList.size(); i++) {
                config = configList.get(i);
                if (maxValue <= first) {
                    //两个break 是为了防止数组下标越界
                    break;
                }
                for (int j = first; j < config.num; j++) {
                    if (maxValue <= j) {
                        break;
                    }
//                if (rankType.equals(SGCommonProto.E_RANK_TYPE.RANK_TYPE_BOSS)){
//                    if (rankList.get(j).getValue() < (long)bossRewardConfig.intValue){
//                        LogUtils.info(rankList.get(j).getObjectIndex() + "伤害不达标 不发放奖励  rankList.get(j).getValue() <" + bossRewardConfig.intValue);
//                        continue;
//                    }
//                }
                    AuctionRewardPlayer auctionRewardPlayer = new AuctionRewardPlayer();
                    auctionRewardPlayer.setObjectIndex(ranks.get(j).getObjectIndex());
                    //名次是list中的索引+1
                    auctionRewardPlayer.addRewardMail(createRankMail(config, j + 1, SGCommonProto.E_RANK_TYPE.RANK_TYPE_CAMP));
                    savePlayerMap.put(ranks.get(j).getObjectIndex(), auctionRewardPlayer);
                }
                first = config.num;
            }
            auctionPlayerUpdate(savePlayerMap);
        }catch (Exception e){
            e.printStackTrace();
            LogUtils.errorException(e);
            return false;
        }
        return true;
    }

    /**
     * 排行榜 奖励发放
     */
    public void rankRewardRest(SGCommonProto.E_RANK_TYPE rankType){

        /**
         * 1.根据ranktype 获取配置文件 找到要发放奖励的总人数
         * 2.根据ranktype 从rankMap中获取该类型排行有奖励的人
         * 3.找到这些用户
         * 4.根据config发送邮件奖励
         * 5.离线玩家sql save  这里Integer和int做的是值传递不是引用传递
         */
        Integer maxValue = 0;
        TwoTuple<List<RankRewardConfig>,Integer> twoTuple = RankRewardConfig.getConfigListByType(rankType,maxValue);
        List<RankRewardConfig> configList = twoTuple.getFirst();
        maxValue = twoTuple.getSecond();
        List<WorldRankBean> ranks = WorldInfoFactory.getInstance().getWorldRankData().getRankList(rankType, maxValue);
        if (ranks == null){
            return;
        }
        List<WorldRankBean> rankList = new ArrayList<>();
        rankList.addAll(ranks);
        //保存昨天排行
        RecordManager.getInstance().addLastRankMap(SGCommonProto.E_RANK_TYPE.RANK_TYPE_WORLDMAP, rankList);
        //复制完成 之后就直接清空
        //战场争锋才会清空
        if (rankType.equals(SGCommonProto.E_RANK_TYPE.RANK_TYPE_WORLDMAP))
            WorldInfoFactory.getInstance().getWorldRankData().reset();

        if (ranks.isEmpty()){
            LogUtils.info(rankType.name() + " rankList size is 0");
            return;
        }
        maxValue = ranks.size();

        Map<String,AuctionRewardPlayer> savePlayerMap = new HashMap<>();

        /**
         * configList 是有序的 , rankList 也是有序的
         * first 是上一个config的num
         */
        int first = 0;
        RankRewardConfig config;
        //上榜就发奖励 不看伤害
//        StableDataConfig bossRewardConfig = null;
//        if (rankType.equals(SGCommonProto.E_RANK_TYPE.RANK_TYPE_BOSS)){
//            bossRewardConfig = DataFactory.getInstance().getGameObject(DataFactory.STABLE_DATA_KEY,E_StableDataType.BOSS_CHALLENGE_BUY.getCode());
//            if (bossRewardConfig == null){
//                LogUtils.error(" StableDataConfig is null ->" + E_StableDataType.BOSS_CHALLENGE_BUY.getCode());
//                return;
//            }
//        }
        for (int i = 0; i < configList.size(); i ++){
            config = configList.get(i);
            if (maxValue <= first){
                //两个break 是为了防止数组下标越界
                break;
            }
            for (int j = first; j < config.num;j++){
                if (maxValue <= j){
                    break;
                }
//                if (rankType.equals(SGCommonProto.E_RANK_TYPE.RANK_TYPE_BOSS)){
//                    if (rankList.get(j).getValue() < (long)bossRewardConfig.intValue){
//                        LogUtils.info(rankList.get(j).getObjectIndex() + "伤害不达标 不发放奖励  rankList.get(j).getValue() <" + bossRewardConfig.intValue);
//                        continue;
//                    }
//                }
                AuctionRewardPlayer auctionRewardPlayer = new AuctionRewardPlayer();
                auctionRewardPlayer.setObjectIndex(rankList.get(j).getObjectIndex());
                //名次是list中的索引+1
                auctionRewardPlayer.addRewardMail(createRankMail(config,j+1,rankType));
                savePlayerMap.put(rankList.get(j).getObjectIndex(),auctionRewardPlayer);
            }
            first = config.num;
        }
        auctionPlayerUpdate(savePlayerMap);
    }

    public MailDB createRankMail(RankRewardConfig config,int j,SGCommonProto.E_RANK_TYPE rankType){
        MailConfig mailConfig = null;
        if (rankType.equals(SGCommonProto.E_RANK_TYPE.RANK_TYPE_WORLDMAP))
            mailConfig = DataFactory.getInstance().getGameObject(
                    DataFactory.MAIL_MODEL_KEY, E_MailModelType.WORLD_MAP_RANK_REWARD.getCode());
        else if (rankType.equals(SGCommonProto.E_RANK_TYPE.RANK_TYPE_BOSS))
            mailConfig = DataFactory.getInstance().getGameObject(
                    DataFactory.MAIL_MODEL_KEY, E_MailModelType.BOSS_BATTLE_RANK_REWARD.getCode());
        else if (rankType.equals(SGCommonProto.E_RANK_TYPE.RANK_TYPE_CAMP))
            mailConfig = DataFactory.getInstance().getGameObject(
                    DataFactory.MAIL_MODEL_KEY, E_MailModelType.CAMP_RANK_REWARD.getCode());
        else{
            LogUtils.error("rankType error ->" + rankType.name());
            return null;
        }
        MailDB mailDB = new MailDB(mailConfig.title, MessageFormat.format(mailConfig.content,j),Arrays.asList(config.reward));
        return mailDB;
    }

    public MailDB hegemonyRankNotRewardMail(E_MailModelType mailModelType,Integer... params){
        MailConfig mailConfig = DataFactory.getInstance().getGameObject(DataFactory.MAIL_MODEL_KEY,mailModelType.getCode());
        if (params == null || params.length == 0 || mailConfig == null){
            LogUtils.error("争霸赛未获得奖励 邮件发送错误");
            return null;
        }
        MailDB mailDB = new MailDB(mailConfig.title,MessageFormat.format(mailConfig.content,params),null);
        return mailDB;
    }

    public MailDB hegemonyRankRewardMail(GoodsData[] reward,E_MailModelType mailType,int rank){
        MailConfig mailConfig = DataFactory.getInstance().getGameObject(
                DataFactory.MAIL_MODEL_KEY, mailType.getCode());
        MailDB mailDB = new MailDB(mailConfig.title, MessageFormat.format(mailConfig.content,rank),Arrays.asList(reward));
        return mailDB;
    }

    /**
     * 限时活动到期后分发奖励
     * @param reward
     * @param mailType
     * @param rewad
     * @return
     */
    public MailDB timeLimitActivityRewadMail(List<GoodsData> reward,E_MailModelType mailType,int rewad){
        MailConfig mailConfig = DataFactory.getInstance().getGameObject(
                DataFactory.MAIL_MODEL_KEY,mailType.getCode());
        MailDB mailDB = new MailDB(mailConfig.title, MessageFormat.format(mailConfig.content,rewad),reward);
        return mailDB;
    }

    /**
     * 每周日24点进行 争霸赛排行奖励分发
     * @param allPlayer
     * @param rankBeanList
     * @param updateMap
     */
    public void hegemonyRankReward(Map<String,Player> allPlayer,List<WorldRankBean> rankBeanList,Map<String,Player> updateMap){
        WorldRankData worldRankData = WorldInfoFactory.getInstance().getWorldRankData();
        HegemonyRankRewardGroupConfig groupConfig = worldRankData.getRewardGroup(SGCommonProto.E_RANK_TYPE.RANK_TYPE_MAPCURRWEEK);
        List<HegemonyRankRewardConfig> rewardConfigList = HegemonyRankRewardConfig.getRewardConfigList(groupConfig.groupId);
        //判断是否达到得分标准
        WorldMapKillBean currentBean = null;
        HegemonyRankRewardConfig rewardConfig = null;
        MailInfo mailInfo = null;
        MailDB notReward = null;
        Player player = null;
        E_MailModelType mailModelType = null;
        PlayerController playerController = null;
        for (int i = 0; i < rewardConfigList.size(); i++){
            rewardConfig = rewardConfigList.get(i);
            for (int j = (i == 0? 0:rewardConfigList.get(i-1).num); (j < rewardConfig.num && j < rankBeanList.size()); j++){
                player = allPlayer.get(rankBeanList.get(j).getObjectIndex());
                if (player == null){
                    LogUtils.error("player is null objectIndex->" + rankBeanList.get(j).getObjectIndex());
                    continue;
                }
                playerController = getPlayerController(player.objectIndex);

                if (playerController != null)
                    player = playerController.getPlayer();

//                if (player == null){
//                    LogUtils.error("player is null objectIndex -> " + rankBeanList.get(j).getObjectIndex());
//                    continue;
//                }
                currentBean = player.getWorldMapKillData().getWorldMapKillBean(E_WorldMapKillRankType.CURRENT_WEEK_RANK);
                if(currentBean == null){
                    continue;
                }
                mailModelType = null;
                mailInfo = player.getExtInfo(MailInfo.class);
                if (currentBean.getMaxValue() >= groupConfig.score){
                    //奖励
                    mailInfo.addMail(SGCommonProto.E_MAIL_TYPE.MAIL_TYPE_SYSTEM_VALUE,hegemonyRankRewardMail(rewardConfig.reward,E_MailModelType.HEGEMONY_RANK_REWARD,j+1));
                }else{
                    //通知玩家不发放争霸赛奖励
                    mailModelType = E_MailModelType.HEGEMONY_NOT_RANK_REWARD;
                }
                if (currentBean.getTotalValue() >= groupConfig.cumulativeScore){
                    //超级奖励
                    mailInfo.addMail(SGCommonProto.E_MAIL_TYPE.MAIL_TYPE_SYSTEM_VALUE, hegemonyRankRewardMail(rewardConfig.superReward,E_MailModelType.HEGEMONY_RANK_SUPER_REWARD,j+1));
                }else{
                    //通知玩家不达标不发放超级奖励
                    if (mailModelType == null)
                        mailModelType = E_MailModelType.HEGEMONY_NOT_RANK_SUPER_REWARD;
                    else if (mailModelType == E_MailModelType.HEGEMONY_NOT_RANK_REWARD)
                        mailModelType = E_MailModelType.HEGEMONY_NOT_ALL_REWARD;
                }
                notReward = null;
                if (mailModelType != null){
                    switch (mailModelType){
                        case HEGEMONY_NOT_RANK_REWARD:
                            //参数玩家争霸赛积分
                            notReward = hegemonyRankNotRewardMail(mailModelType,currentBean.getMaxValue());
                            break;
                        case HEGEMONY_NOT_RANK_SUPER_REWARD:
                            //
                            notReward = hegemonyRankNotRewardMail(mailModelType,currentBean.getTotalValue());
                            break;
                        case HEGEMONY_NOT_ALL_REWARD:
                            notReward = hegemonyRankNotRewardMail(mailModelType,currentBean.getMaxValue(),currentBean.getTotalValue());
                            break;
                         default:
                             LogUtils.error("通知 争霸赛未获得奖励邮件出错");
                    }
                }

                if (notReward != null)
                    mailInfo.addMail(SGCommonProto.E_MAIL_TYPE.MAIL_TYPE_SYSTEM_VALUE,notReward);

                if (playerController == null){
                    //可以进行保存玩家的信息
                    updateMap.put(player.getObjectIndex(),player);
                }
            }
        }
    }

//    public TwoTuple<Integer, Integer> getPlayerMapHP(String playerIndex)
//    {
//        TwoTuple<Integer, Integer> result = new TwoTuple<Integer, Integer>();
//        SpritePlayerBean spritePlayerBean = WorldInfoFactory.getInstance().getWorldMapData().getPlayerActionBean(playerIndex);
//        if(spritePlayerBean == null)
//        {
//            result.setFirst(100);
//            result.setSecond(100);
//        }
//        else
//        {
//            result.setFirst(spritePlayerBean.getBattleTemp().getMasterHPRate());
//            result.setSecond(spritePlayerBean.getBattleTemp().getArmyHPRate());
//        }
//        return result;
//    }

    /**
     *
     * @param worldRankData
     */
    public void checkMondy(WorldRankData worldRankData){
        Map<Integer, List<WorldRankBean>> rankMap = worldRankData.getRankMap();
        List<WorldRankBean> current = rankMap.get(SGCommonProto.E_RANK_TYPE.RANK_TYPE_MAPCURRWEEK_VALUE);
        //将争霸赛数据缓存
        RecordManager.getInstance().addLastRankMap(SGCommonProto.E_RANK_TYPE.RANK_TYPE_MAPLASTWEEK, current);
        List<WorldRankBean> last = new ArrayList<>();
        int len = current.size() > 10 ? 10 : current.size();
        int allLv = 0;
        RankPlayerDetail rankPlayerDetail = null;

        for (int i = 0; i < len; i ++){
            if (current.get(i) != null){
                if (i < 3){
                    last.add(current.get(i));
                }
                rankPlayerDetail = getRankPlayer(current.get(i).getObjectIndex());
                allLv += rankPlayerDetail.getLv();
            }else{
                break;
            }
        }
        int level = len == 0 ? 1 : allLv / len;
        //设置上次前十的平均等级
        worldRankData.getRewardGroupMap().put(SGCommonProto.E_RANK_TYPE.RANK_TYPE_MAPCURRWEEK_VALUE,level);
        /**
         * 根据等级分组分发奖励
         */
        rankMap.put(SGCommonProto.E_RANK_TYPE.RANK_TYPE_MAPCURRWEEK_VALUE, new ArrayList<>());
        rankMap.put(SGCommonProto.E_RANK_TYPE.RANK_TYPE_MAPLASTWEEK_VALUE,last);
        //当开服第一周都没有人点击过争霸赛排行榜的时候造成的bug
        worldRankData.getRankStatus().put(SGCommonProto.E_RANK_TYPE.RANK_TYPE_MAPCURRWEEK_VALUE, SGCommonProto.E_MAP_HEGEMONY_RANK_TYPE.WORLD_MAP_RANk_CURRENT_DRESS_VALUE);
        worldRankData.getRankStatus().put(SGCommonProto.E_RANK_TYPE.RANK_TYPE_MAPLASTWEEK_VALUE, SGCommonProto.E_MAP_HEGEMONY_RANK_TYPE.WORLD_MAP_RANk_CURRENT_DRESS_VALUE);
    }

    /**
     * 更新白名单
     */
    public void updateWhite(){
        JSONObject jsonObject = HttpJsonUtils.httpPost(GameServer.getInstance().getAuthServerHost() + HttpFactory.PLAYER_GET_WHITE_LIST);
        if (jsonObject == null)
            return;
        List<String> list = (List<String>) jsonObject.get("data");
        whiteList = list;
        LogUtils.info("update whiltList successfully！");
    }

    /**
     * 是否是白名单
     * @param account
     * @return
     */
    public boolean isWhite(String account){
        return StringUtils.isNullOrEmpty(account) ? false :whiteList.contains(account);
    }

    /**
     * 限时活动检测
     * @param calendar
     */
    public void timeLimitActivityCheck(Calendar calendar){
        List<TimeLimitedActivitiesConfig> configs = DataFactory.getInstance().getDataList(DataFactory.TIME_LIMIT_ACTIVITY_KEY);
        List<TimeLimitedActivitiesConfig> configList = new CopyOnWriteArrayList<>();
        configs.forEach((config)->{
            if (config.isServerIn(WorldInfoFactory.getInstance().getServerId()) && config.isLastDay(calendar))
                configList.add(config);
        });

        //得到了所有符合条件的限时活动
        if (!configList.isEmpty())
            GameServer.getInstance().startThread(()-> updateAllPlayerLimitActicity(configList,calendar));
    }

    /**
     * 1.找到所有的玩家
     * 2.去认证服查找相关记录 发放邮件奖励
     * @param configList
     */
    private void updateAllPlayerLimitActicity(List<TimeLimitedActivitiesConfig> configList,Calendar calendar){
        List<Player> allPlayer = getAllPlayerList();
        List<Player> savePlayer = new CopyOnWriteArrayList<>();
        PlayerService playerService = SpringContext.getBean(PlayerService.class);
        configList.forEach((config) -> {
            if (config.type == E_TimeLimitActivityType.TOTAL_RECHARGE.getCode() || config.type == E_TimeLimitActivityType.TOTAL_DIAMONDS.getCode()){
                List<GoodsData> temp = new CopyOnWriteArrayList<>(config.reward);
                TwoTuple<Long,Long> inDayTime = CoreUtils.getNewTimeActivity(calendar);
                allPlayer.forEach((player) ->{
                        //如果是累计充值的类型 重新统计累计充值
                        if (config.type == E_TimeLimitActivityType.TOTAL_RECHARGE.getCode()){
                            playerService.queryTotalRechargeCount(player,inDayTime.getFirst(),inDayTime.getSecond());
                        }
                        AtomicInteger rechargeCount = new AtomicInteger(0);
                        if (config.type == E_TimeLimitActivityType.TOTAL_RECHARGE.getCode())
                            rechargeCount.set(player.getRechargeData().getRechargeCount(E_QueryRechargeCountType.DEFINE.getCode()));
                        else
                            rechargeCount.set(player.getBonusData().getDiamondsCacheDefine());
                        List<GoodsData> rewardList = new CopyOnWriteArrayList<>();
                        temp.forEach((r)->{
                            if (rechargeCount.get() > r.extraValue[0] && player.getBonusData().hasReceiveActivityReward(config.id, r.extraValue[0])){
                                //说明冲得钱够 并且未领取过的奖励
                                rewardList.add(r);
                            }
                        });
                        //然后将玩家的所有奖励更新成已领取 但是不能和领取奖励在同一个循环 因为这里玩家福利信息中存储的奖励id是玩家充值的金额 可能对应多个奖励
                        temp.forEach((r)->{
                            if (rechargeCount.get() > r.extraValue[0] && !player.getBonusData().hasReceiveActivityReward(config.id, r.extraValue[0])){
                                //说明冲得钱够 并且未领取过的奖励
                                player.getBonusData().addActivityReward(config.id,r.extraValue[0]);
                            }
                        });
                        //这时候进行邮件发放
                        if (!rewardList.isEmpty()){
                            if (config.type == E_TimeLimitActivityType.TOTAL_RECHARGE.getCode())
                                player.getExtInfo(MailInfo.class).addMail(SGCommonProto.E_MAIL_TYPE.MAIL_TYPE_SYSTEM_VALUE,timeLimitActivityRewadMail(rewardList,E_MailModelType.TIME_LIMIT_ACTIVITY_RECHARGE_REWARD,rechargeCount.get()));
                            else
                                player.getExtInfo(MailInfo.class).addMail(SGCommonProto.E_MAIL_TYPE.MAIL_TYPE_SYSTEM_VALUE,timeLimitActivityRewadMail(rewardList,E_MailModelType.TIME_LIMIT_ACTIVITY_DIAMONDS_REWARD,rechargeCount.get()));
                            savePlayer.add(player);
                        }
                });
            }
        });

        //保存所有玩家信息
        GameServer.getInstance().savePlayerListSync(savePlayer, false, BoonInfo.class, MailInfo.class);
    }



    /**
     * 验证开始
     * @param outTradeNo
     */
    public void verifyTradeStart(String outTradeNo)
    {
        verifyingTradeList.add(outTradeNo);
    }

    public void verifyTradeEnd(String outTradeNo)
    {
        verifyingTradeList.remove(outTradeNo);
    }

    public boolean isVerifying(String outTradeNo)
    {
        return verifyingTradeList.contains(outTradeNo);
    }


    /**
     * 时间到了奖励发放排行邮件奖励
     */
    public static void timeTopRankCheck() {
        //当前时间
        Date currentTime = new Date();
        List<SevenTabConfig> tabConfigList =  DataFactory.getInstance().getDataList(DataFactory.SEVEN_TAB);
        long endTime = 0;
        TimeData timeData =null;
        for (SevenTabConfig config:tabConfigList){
            if (config.type == E_SevenDayActiType.ACTIVITIES_TOP_REWARD.getCode()){
                long[] time =  TimeUtils.getActivityTime(config.startTime,GameServer.startTime);
                endTime =time[1];
                timeData = config.startTime;
                break;
            }
        }
        Calendar now = Calendar.getInstance();
        Boolean isInActivityTime = TimeUtils.isInActivityTime(timeData, now, GameServer.startTime);
        //当前时间和结束时间相同则发送排行榜奖励
        int currentDays = TimeUtils.dayBetween(new Date(endTime),currentTime);
        //发奖励 与活动结束时间间隔0天且没在活动时间内了 防止配置没配0点
        if (currentDays == 0 && !isInActivityTime) {
            Map<Integer, List<WorldRankBean>> getRankMap = WorldInfoFactory.getInstance().getWorldRankData().getRankMap();
            LogUtils.info("开始发送开服排名奖励......");
            //WorldInfoFactory worldInfo = WorldInfoFactory.getInstance();
            //排行类型，排行名次奖励配置
            Map<Integer, List<SevenActivitiesConfig>> configMap = new HashMap<>();
            //获取竞技场排行配置
            List<SevenActivitiesConfig> sevenActivitiesConfigList = DataFactory.getInstance().getDataList(DataFactory.SEVEN_DAY_REWARD);
            SevenTabConfig tabConfig ;
            for (SevenActivitiesConfig config : sevenActivitiesConfigList) {
                tabConfig= DataFactory.getInstance().getGameObject(DataFactory.SEVEN_TAB, config.groupId);

                if (tabConfig.type == E_SevenDayActiType.ACTIVITIES_TOP_REWARD.getCode() && config.rewardMod == SevenDayFactory.REWARD_MOD_2) {
                    if (configMap.get(config.eventType) == null) {
                        configMap.put(config.eventType, new ArrayList<>());
                    }
                    List<SevenActivitiesConfig> list = configMap.get(config.eventType);
                    list.add(config);
                }
            }
            List<SevenActivitiesConfig> configList;
            List<WorldRankBean> ranks;
            MailConfig mailConfig;
            MailDB mailDB;
            Map<String, AuctionRewardPlayer> savePlayerMap;
            Map<Integer,Map<String, AuctionRewardPlayer>> allSavePlayerMap =new HashMap<>();
            AuctionRewardPlayer auctionRewardPlayer;
            //*****1.竞技排行 ***********//
            LogUtils.info("开始发送开服竞技场排名奖励......");
            configList = configMap.get(SevenDayFactory.EVENT_TYPE_17);
            savePlayerMap = new HashMap<>();
            for (SevenActivitiesConfig config : configList) {
                //config参数个数错误
                if (config.conditionParam.length != 2) {
                    break;
                }
                List<WorldArenaBean> arenaBeanList =  GameServer.getInstance().getWorldArenaData().getUnderTargetRankList( config.conditionParam[0], config.conditionParam[1]);

                for (int i = 0; i < arenaBeanList.size(); i++) {
                    auctionRewardPlayer = new AuctionRewardPlayer();
                    auctionRewardPlayer.setObjectIndex(arenaBeanList.get(i).getObjectIndex());
                    // 邮件config
                    mailConfig = DataFactory.getInstance().getGameObject(
                            DataFactory.MAIL_MODEL_KEY, E_MailModelType.OPEN_SERVER_ACTIVITIES_ARENA.getCode());
                    mailDB = new MailDB(mailConfig.title, MessageFormat.format(mailConfig.content, i+1), Arrays.asList(config.rewardItem));
                    //名次是list中的索引+1
                    auctionRewardPlayer.addRewardMail(mailDB);
                    savePlayerMap.put(arenaBeanList.get(i).getObjectIndex(), auctionRewardPlayer);
                }
            }
            allSavePlayerMap.put(SevenDayFactory.EVENT_TYPE_17,savePlayerMap);
            //******2.战力排行 ***********//
            LogUtils.info("开始发送开服战力排名奖励......");
            configList = configMap.get(SevenDayFactory.EVENT_TYPE_18);
            savePlayerMap = new HashMap<>();
            for (SevenActivitiesConfig config : configList) {
                if (config.conditionParam.length != 2) {
                    break;
                }
                ranks = WorldInfoFactory.getInstance().getWorldRankData().
                        getRankList(getRankMap,SGCommonProto.E_RANK_TYPE.RANK_TYPE_FC, config.conditionParam[0], config.conditionParam[1]);
                for (int i =0; i < ranks.size(); i++) {
                    auctionRewardPlayer = new AuctionRewardPlayer();
                    auctionRewardPlayer.setObjectIndex(ranks.get(i).getObjectIndex());
                    // 邮件config
                    mailConfig = DataFactory.getInstance().getGameObject(
                            DataFactory.MAIL_MODEL_KEY, E_MailModelType.OPEN_SERVER_ACTIVITIES_FC.getCode());
                    mailDB = new MailDB(mailConfig.title, MessageFormat.format(mailConfig.content,ranks.get(i).getValue(), config.conditionParam[0]+i+1), Arrays.asList(config.rewardItem));
                    //名次是list中的索引+1
                    auctionRewardPlayer.addRewardMail(mailDB);
                    savePlayerMap.put(ranks.get(i).getObjectIndex(), auctionRewardPlayer);
                }
            }
            allSavePlayerMap.put(SevenDayFactory.EVENT_TYPE_18,savePlayerMap);

            //**************3.充值排行 ***********//
            LogUtils.info("开始发送开服充值排名奖励......");
            configList = configMap.get(SevenDayFactory.EVENT_TYPE_19);
            savePlayerMap = new HashMap<>();
            for (SevenActivitiesConfig config : configList) {
                if (config.conditionParam.length != 2) {
                    break;
                }
                ranks = WorldInfoFactory.getInstance().getWorldRankData().
                        getRankList(getRankMap,SGCommonProto.E_RANK_TYPE.RANK_TYPE_MONEY, config.conditionParam[0], config.conditionParam[1]);
                for (int i =0; i < ranks.size(); i++) {
                    auctionRewardPlayer = new AuctionRewardPlayer();
                    auctionRewardPlayer.setObjectIndex(ranks.get(i).getObjectIndex());
                    // 邮件config
                    mailConfig = DataFactory.getInstance().getGameObject(
                            DataFactory.MAIL_MODEL_KEY, E_MailModelType.OPEN_SERVER_ACTIVITIES_MONEY.getCode());
                    mailDB = new MailDB(mailConfig.title, MessageFormat.format(mailConfig.content,ranks.get(i).getValue(), config.conditionParam[0]+i+1), Arrays.asList(config.rewardItem));
                    //名次是list中的索引+1
                    auctionRewardPlayer.addRewardMail(mailDB);
                    savePlayerMap.put(ranks.get(i).getObjectIndex(), auctionRewardPlayer);
                }
            }
            allSavePlayerMap.put(SevenDayFactory.EVENT_TYPE_19,savePlayerMap);
            //************4.远征排行 ***********//
            LogUtils.info("开始发送开服远征排名奖励......");
            configList = configMap.get(SevenDayFactory.EVENT_TYPE_20);
            savePlayerMap = new HashMap<>();
            for (SevenActivitiesConfig config : configList) {
                if (config.conditionParam.length != 2) {
                    break;
                }
                ranks = WorldInfoFactory.getInstance().getWorldRankData().
                        getRankList(getRankMap,SGCommonProto.E_RANK_TYPE.RANK_TYPE_EXPEDITION, config.conditionParam[0], config.conditionParam[1]);
                for (int i =0; i < ranks.size(); i++) {
                    auctionRewardPlayer = new AuctionRewardPlayer();
                    auctionRewardPlayer.setObjectIndex(ranks.get(i).getObjectIndex());
                    // 邮件config
                    mailConfig = DataFactory.getInstance().getGameObject(
                            DataFactory.MAIL_MODEL_KEY, E_MailModelType.OPEN_SERVER_ACTIVITIES_EXPEDITION.getCode());
                    mailDB = new MailDB(mailConfig.title, MessageFormat.format(mailConfig.content, config.conditionParam[0]+i+1), Arrays.asList(config.rewardItem));
                    //名次是list中的索引+1
                    auctionRewardPlayer.addRewardMail(mailDB);
                    savePlayerMap.put(ranks.get(i).getObjectIndex(), auctionRewardPlayer);
                }
            }
            allSavePlayerMap.put(SevenDayFactory.EVENT_TYPE_20,savePlayerMap);
            //*********5 副本排行 ***********//
            LogUtils.info("开始发送副本远征排名奖励......");
            configList = configMap.get(SevenDayFactory.EVENT_TYPE_21);
            savePlayerMap = new HashMap<>();
            for (SevenActivitiesConfig config : configList) {
                if (config.conditionParam.length != 2) {
                    break;
                }
                ranks = WorldInfoFactory.getInstance().getWorldRankData().
                        getRankList(getRankMap,SGCommonProto.E_RANK_TYPE.RANK_TYPE_INSTANCE, config.conditionParam[0], config.conditionParam[1]);
                for (int i =0; i < ranks.size(); i++) {
                    auctionRewardPlayer = new AuctionRewardPlayer();
                    auctionRewardPlayer.setObjectIndex(ranks.get(i).getObjectIndex());
                    // 邮件config
                    mailConfig = DataFactory.getInstance().getGameObject(
                            DataFactory.MAIL_MODEL_KEY, E_MailModelType.OPEN_SERVER_ACTIVITIES_INSTANCE.getCode());
                    mailDB = new MailDB(mailConfig.title, MessageFormat.format(mailConfig.content, config.conditionParam[0]+i+1), Arrays.asList(config.rewardItem));
                    //名次是list中的索引+1
                    auctionRewardPlayer.addRewardMail(mailDB);
                    savePlayerMap.put(ranks.get(i).getObjectIndex(), auctionRewardPlayer);
                }
            }
            allSavePlayerMap.put(SevenDayFactory.EVENT_TYPE_21,savePlayerMap);
            auctionPlayerUpdateByActi(allSavePlayerMap);
        }
    }

    /**
     * 排行榜邮件执行数据库保存
     * @param allSavePlayerMap
     */
    public static void auctionPlayerUpdateByActi(Map<Integer, Map<String, AuctionRewardPlayer>> allSavePlayerMap) {

        if (allSavePlayerMap.size() <= 0) {
            LogUtils.info("排行榜开服活动没有发送邮件的数据");
            return;
        }
        List<Player> savePlayerList;
        TwoTuple<Player, PlayerController> twoTuple;
        Player player;
        //循环保存玩家排行榜邮件信息
        for (Map<String, AuctionRewardPlayer> savePlayerMap :allSavePlayerMap.values()){
            if (savePlayerMap.size()<= 0){
                continue;
            }
            savePlayerList = new ArrayList<>();
            for (Map.Entry<String, AuctionRewardPlayer> entry : savePlayerMap.entrySet()) {
                twoTuple = GameServer.getInstance().getWorldManager().getPlayerResult(entry.getKey());

                player = twoTuple.getFirst();
                if (player == null) {
                    continue;
                }
                player.getBonusData().addAuctionReward(entry.getValue().getTotalRewardMoney());
                if (entry.getValue().getRewardMailList() != null && entry.getValue().getRewardMailList().size() > 0) {
                    for (MailDB mailDB : entry.getValue().getRewardMailList()) {
                        MailInfo mailInfo = twoTuple.getFirst().getExtInfo(MailInfo.class);
                        mailInfo.addMail(SGCommonProto.E_MAIL_TYPE.MAIL_TYPE_SYSTEM_VALUE, mailDB);
                    }
                }
                if (!savePlayerList.contains(player))
                savePlayerList.add(player);
            }
            if (savePlayerList.size() > 0) {
                GameServer.getInstance().savePlayerList(savePlayerList, false, MailInfo.class);
            }
        }
    }

    public void clearAllPlayer()
    {
        playerList.clear();
        playerIndexMap.clear();

        currentPlayerCount = 0;
        waitPlayerMap.clear();

        connections.clear();
    }



}
